﻿using Crawler.Common;
using Crawler.Core.Analyzer;
using Crawler.Core.CrawlerHandler.UrlChecker;
using Crawler.Core.EventBus;
using Crawler.IRepositories;
using Crawler.Model.SystemDefault;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace Crawler.Core.CrawlerHandler.Analyzer
{
    public class AnalyzerHandler : IEventHandler<AnalyzerEventEntity>
    {
        private Dictionary<int, IAnalyzer> analyzers;

        private readonly IRepository<CollectInfoConfigModel> collectInfoConfigRepository;
        private readonly IRepository<PageInfoModel> pageInfoRepository;
        private readonly IRepository<TerminalConfigModel> terminalConfigRepository;
        private readonly IServiceProvider service;
        private readonly AnalyzerManager analyzerManager;
        private readonly IEventBus eventBus;

        public AnalyzerHandler(
            IRepository<CollectInfoConfigModel> collectInfoConfigRepository
            , IRepository<PageInfoModel> pageInfoRepository
            , IEventBus eventBus
            , IRepository<TerminalConfigModel> terminalConfigRepository
            , IServiceProvider service
            , AnalyzerManager analyzerManager
            )
        {
            analyzers = new Dictionary<int, IAnalyzer>();
            this.collectInfoConfigRepository = collectInfoConfigRepository;
            this.pageInfoRepository = pageInfoRepository;
            this.eventBus = eventBus;
            this.terminalConfigRepository = terminalConfigRepository;
            this.service = service;
            this.analyzerManager = analyzerManager;


        }

        public void Trigger(AnalyzerEventEntity entity)
        {

            var pageModel = entity.pageInfoModel;
            if (pageModel == null) return;
            //获取配置信息
            var configModel = collectInfoConfigRepository.Find(pageModel.CollectorConfigID);
            //配置设置停止则终止
            if (configModel == null || configModel.WorkStatus != WorkStatus.Running)
            {
                //Console.WriteLine("-----Analyzer Stop");
                return;
            }
            lock (configModel.ID.ToString())
            {
                //获取终端配置
                var terminalConfig = terminalConfigRepository.Find(Constant.AppSetting.TerminalId);

                Assembly assembly = Assembly.Load(new AssemblyName("Crawler.Framework"));
                IAnalyzer analyzer = GetAnalyzer(configModel, assembly);
                if (analyzer != null)
                {
                    Console.WriteLine("-----Analyzer Analyze:" + pageModel.Url);
                    analyzer.Analyze(pageModel.Url, pageModel.Html, (url, handlerType) =>
                    {
                        var urlModel = new CollectorUrlModel
                        {
                            Url = url,
                            AddTime = DateTime.Now,
                            CollectorConfigID = configModel.ID,
                            Depth = pageModel.Depth,//深度将在url检查器 +1 
                            ErrorTimes = 0,
                            CollectStatus = CollectStatus.Default
                        };

                        if (handlerType == HandlerType.ReSetDepth) urlModel.Depth -= 1;
                        if (handlerType == HandlerType.ReCollect)
                        {
                            urlModel.ReCollectTimes += 1;
                            urlModel.Depth -= 1;
                            urlModel.CollectStatus = CollectStatus.ReCollect;
                        }
                        //重新采集超过一定次数将放弃
                        if (terminalConfig.MaxReCollectTimes < 1) terminalConfig.MaxReCollectTimes = 0;
                        if (urlModel.ReCollectTimes > terminalConfig.MaxReCollectTimes) return;
                        //发布事件，等待采集
                        eventBus.Publish(new UrlCheckerEventEntity { collectorUrlModel = urlModel });

                    }, configModel.ID);

                    //最后更新为已解析
                    pageModel.AnalyzeStatus = AnalyzeStatus.Analyzed;
                    pageInfoRepository.Update(pageModel);
                }
            }
        }

        private IAnalyzer GetAnalyzer(CollectInfoConfigModel configModel, Assembly assembly)
        {
            if (!analyzers.ContainsKey(configModel.ID))
            {
                lock ("dicHandlerInstances")
                {
                    if (!analyzers.ContainsKey(configModel.ID))
                    {
                        IAnalyzer analyzer;
                        //默认解析
                        if (configModel.AnalyzeType == AnalyzeType.Default)
                        {
                            Type type = assembly.GetType("Crawler.Framework.Analyzers.DefaultAnalyzer");
                            analyzer = (IAnalyzer)service.GetService(type);
                        }
                        else
                        {
                            //TODO 根据插件解析,默认这里通过反射 OpenImplement，这里还讲继续改进载入指定地址 dll
                            Type type = analyzerManager.GetAnalyzerTypeByFullName(configModel.PluginPath);
                            analyzer = (IAnalyzer)service.GetService(type);
                        }
                        analyzers.Add(configModel.ID, analyzer);
                    }
                }
            }
            return analyzers[configModel.ID];
        }
    }
}
